// Copyright (c) 2023 Huawei Device Co., Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::structure::*;

/// XML Declaration parts.
#[derive(Debug)]
pub(crate) struct XmlDecl {
    pub(crate) version: String,
    pub(crate) standalone: Option<bool>,
    pub(crate) xml_encoding: Option<Encoding>,
}

impl XmlDecl {
    /// Get xml encoding.
    pub(crate) fn xml_encoding(&self) -> Option<Encoding> {
        self.xml_encoding.clone()
    }

    /// Set xml encoding.
    pub(crate) fn set_xml_encoding(&mut self, xml_encoding: Option<Encoding>) {
        self.xml_encoding = xml_encoding;
    }

    /// Get xml version.
    pub(crate) fn version(&self) -> String {
        self.version.clone()
    }

    /// Set xml version.
    pub(crate) fn set_version(&mut self, version: &str) -> Result<(), XmlError> {
        if !is_version_num(version) {
            return Err(DomException::InvalidCharacterErr.into());
        }
        self.version = version.to_string();
        Ok(())
    }

    /// Get standalone.
    pub(crate) fn standalone(&self) -> Option<bool> {
        self.standalone
    }

    /// Set standalone.
    pub fn set_standalone(&mut self, standalone: Option<bool>) {
        self.standalone = standalone;
    }
}

impl Default for XmlDecl {
    fn default() -> Self {
        Self {
            version: "1.0".to_string(),
            standalone: None,
            xml_encoding: None,
        }
    }
}

/// Different character encodings for XML documents.
/// Currently only UTF-8 is supported.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Encoding {
    /// UTF-8 character encoding.
    Utf8,
    // Utf16,
    // Iso10646Ucs2,
    // Iso10646Ucs4,
    // Iso8859_1,
    // Iso8859_2,
    // Iso8859_3,
    // Iso8859_4,
    // Iso8859_5,
    // Iso8859_6,
    // Iso8859_7,
    // Iso8859_8,
    // Iso8859_9,
    // Iso2022Jp,
    // ShiftJis,
    // EucJp,
}

impl Encoding {
    /// Returns a string representation of the encoding.
    pub fn as_str(&self) -> &str {
        match self {
            Self::Utf8 => "UTF-8",
            // Self::Utf16 => "UTF-16",
            // Self::Iso10646Ucs2 => "ISO-10646-UCS-2",
            // Self::Iso10646Ucs4 => "ISO-10646-UCS-4",
            // Self::Iso8859_1 => "ISO-8859-1",
            // Self::Iso8859_2 => "ISO-8859-2",
            // Self::Iso8859_3 => "ISO-8859-3",
            // Self::Iso8859_4 => "ISO-8859-4",
            // Self::Iso8859_5 => "ISO-8859-5",
            // Self::Iso8859_6 => "ISO-8859-6",
            // Self::Iso8859_7 => "ISO-8859-7",
            // Self::Iso8859_8 => "ISO-8859-8",
            // Self::Iso8859_9 => "ISO-8859-9",
            // Self::Iso2022Jp => "ISO-2022-JP",
            // Self::ShiftJis => "Shift_JIS",
            // Self::EucJp => "EUC-JP",
        }
    }
}

#[cfg(test)]
mod ut_xml_decl {
    use crate::structure::Encoding;

    /*
     * @title  UT test for Encoding as_str
     * @design Condition Coverage
     * @precon NA
     * @brief  1. Call Encoding。
     *         2. Call as_str to get content。
     *         3. Compare result
     * @expect 1. true。
     * @auto   yes
     */
    #[test]
    fn ut_xml_decl_as_str() {
        assert_eq!(Encoding::Utf8.as_str(), "UTF-8");
    }
}
